home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / utils / adt / date.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-18  |  27.6 KB  |  1,162 lines

  1. /*
  2.  * date.c --
  3.  *    Functions for the built-in type "AbsoluteTime".
  4.  *    Functions for the built-in type "RelativeTime".
  5.  *    Functions for the built-in type "TimeInterval".
  6.  *
  7.  * Notes:
  8.  *    This code is actually (almost) unused.
  9.  *    It needs to be integrated with Time and struct trange.
  10.  *
  11.  * XXX    This code needs to be rewritten to work with the "new" definitions
  12.  * XXX    in h/tim.h.  Look for int32's, int, long, etc. in the code.  The
  13.  * XXX    definitions in h/tim.h may need to be rethought also.
  14.  */
  15.  
  16. #include <ctype.h>
  17. #include <stdio.h>
  18. #include <sys/time.h>
  19. #include <sys/types.h>
  20. #include <sys/timeb.h>
  21. #include <strings.h>
  22.  
  23. #include "tmp/postgres.h"
  24. #include "tmp/miscadmin.h"
  25. #include "utils/log.h"
  26. #include "utils/nabstime.h"
  27.  
  28. RcsId("$Header: /private/postgres/src/utils/adt/RCS/date.c,v 1.25 1992/06/18 18:16:01 mer Exp $");
  29.  
  30. #define    TM_YEAR_BASE    1900        /* compatible to UNIX time */
  31. #define    EPOCH_YEAR    1970        /* compatible to UNIX time */
  32. #define    YEAR_MAX    2038        /* otherwise overflow */
  33. #define    YEAR_MIN    1902        /* otherwise overflow */
  34. #define    DAYS_PER_LYEAR    366
  35. #define    DAYS_PER_NYEAR    365
  36. #define    HOURS_PER_DAY    24
  37. #define    MINS_PER_HOUR    60
  38. #define    SECS_PER_MIN    60
  39. #define    MAX_LONG    2147483647    /* 2^31 */
  40.  
  41. /* absolute time definitions */
  42. #define    TIME_NOW_STR        "now"       /* represents time now */
  43. #define    TIME_EPOCH_STR        "epoch"       /* Jan 1 00:00:00 1970 GMT */
  44. #define TIME_EPOCH_STR_LEN    (sizeof(TIME_EPOCH_STR)-1)
  45. #ifndef INVALID_ABSTIME
  46. #define    INVALID_ABSTIME        MAX_LONG
  47. #endif    !INVALID_ABSTIME
  48.     /* -2145916801 invalid time representation */
  49.     /*   Dec 31 23:59:59 1901       */
  50. #define    INVALID_ABSTIME_STR     "Undefined AbsTime"
  51. #define    INVALID_ABSTIME_STR_LEN    (sizeof(INVALID_ABSTIME_STR)-1)
  52.  
  53. /*
  54.  *  Unix epoch is Jan  1 00:00:00 1970.  Postgres knows about times
  55.  *  sixty-eight years on either side of that.
  56.  */ 
  57.  
  58. #define    MAX_ABSTIME        2147483647    /* Jan 19 03:14:07 2038 GMT */
  59. #define    MIN_ABSTIME        (0)        /* Jan  1 00:00:00 1970 */
  60.  
  61. /* relative time definitions */
  62. #define    MAX_RELTIME        2144448000
  63.     /* about 68 years, compatible to absolute time */
  64. #define    INVALID_RELTIME        MAX_LONG
  65.     /* invalid reltime representation */
  66. #define    INVALID_RELTIME_STR    "Undefined RelTime"
  67. #define    INVALID_RELTIME_STR_LEN (sizeof(INVALID_RELTIME_STR)-1)
  68. #define    RELTIME_LABEL        '@'
  69. #define    RELTIME_PAST        "ago"
  70. #define    DIRMAXLEN        (sizeof(RELTIME_PAST)-1)
  71.  
  72. #define    InAbsTimeInterval(T) \
  73.     ((int32)(T) <= MAX_ABSTIME && (int32)(T) >= MIN_ABSTIME)
  74. #define    InRelTimeInterval(T) \
  75.     ((int32)(T) <= MAX_RELTIME && (int32)(T) >= - MAX_RELTIME)
  76. #define    IsCharDigit(C)        isdigit(C)
  77. #define    IsCharA_Z(C)        isalpha(C)        
  78. #define    IsSpace(C)        ((C) == ' ')
  79. #define    IsNull(C)        ((C) == NULL)
  80.  
  81. #define    T_INTERVAL_INVAL   0    /* data represents no valid interval */
  82. #define    T_INTERVAL_VALID   1    /* data represents a valid interval */
  83. #define    T_INTERVAL_UNCOM   2    /* data represents an uncomplete interval */
  84. #define    T_INTERVAL_LEN     47    /* 2+20+1+1+1+20+2 : ['...' '...']  */
  85. #define    INVALID_INTERVAL_STR        "Undefined Range"
  86. #define    INVALID_INTERVAL_STR_LEN    (sizeof(INVALID_INTERVAL_STR)-1)
  87.  
  88. static char    *month_name[] = {
  89.     "Jan","Feb","Mar","Apr","May","Jun","Jul",
  90.     "Aug","Sep","Oct","Nov","Dec" };
  91.  
  92. static int    day_tab[2][12] = {
  93.     {31,28,31,30,31,30,31,31,30,31,30,31},
  94.     {31,29,31,30,31,30,31,31,30,31,30,31}  };
  95.  
  96. static    char     *unit_tab[] = {
  97.     "second", "seconds", "minute", "minutes",
  98.     "hour", "hours", "day", "days", "week", "weeks",
  99.     "month", "months", "year", "years"};
  100. #define UNITMAXLEN 7    /* max length of a unit name */
  101.  
  102. /* table of seconds per unit (month = 30 days, year = 365 days)  */
  103. static    int    sec_tab[] = { 
  104.     1,1, 60, 60,
  105.     3600, 3600, 86400, 86400, 604800,  604800,
  106.     2592000,  2592000,  31536000,  31536000 };
  107.  
  108. /* maximal values (in seconds) per unit which can be represented */
  109. static    int    unit_max_quantity[] = {
  110.     2144448000, 2144448000, 35740800, 35740800,
  111.     595680, 595680, 24820, 24820, 3545, 3545,
  112.     827, 827, 68, 68 };
  113.  
  114.  
  115. #ifdef linux
  116. struct tm *CurrentLocalTime = 0;
  117. #else
  118. struct timeb *TimeDifferenceFromGMT = NULL;
  119. #endif
  120. static bool TimeDiffIsInited = false;
  121. static char *timezonename = NULL;
  122.  
  123. /*
  124.  * Function prototypes -- internal to this file only
  125.  */
  126.  
  127. int isabstime ARGS((char *datestring , struct tm *brokentime ));
  128. int correct_month ARGS((char month [], int *num ));
  129. int isleap ARGS((int year ));
  130. int timeinsec ARGS((struct tm *t , AbsoluteTime *seconds ));
  131. int isreltime ARGS((char *timestring , int *sign , long *quantity , int *unitnr ));
  132. int correct_unit ARGS((char unit [], int *unptr ));
  133. int correct_dir ARGS((char direction [], int *signptr ));
  134. int istinterval ARGS((char *i_string , AbsoluteTime *i_start , AbsoluteTime *i_end ));
  135. char *timenowout ARGS((void ));
  136. AbsoluteTime timenow ARGS((void ));
  137. RelativeTime intervalrel ARGS((TimeInterval interval ));
  138. int ininterval ARGS((int32 t , TimeInterval interval ));
  139. AbsoluteTime timemi ARGS((AbsoluteTime AbsTime_t1 , RelativeTime RelTime_t2 ));
  140. char *tintervalout ARGS((TimeInterval interval ));
  141. TimeInterval tintervalin ARGS((char *intervalstr ));
  142. int32 intervaleq ARGS((TimeInterval i1 , TimeInterval i2 ));
  143. int32 intervalleneq ARGS((TimeInterval i , RelativeTime t ));
  144. int32 intervallenne ARGS((TimeInterval i , RelativeTime t ));
  145. int32 intervallenlt ARGS((TimeInterval i , RelativeTime t ));
  146. int32 intervallengt ARGS((TimeInterval i , RelativeTime t ));
  147. int32 intervallenle ARGS((TimeInterval i , RelativeTime t ));
  148. int32 intervallenge ARGS((TimeInterval i , RelativeTime t ));
  149. int32 intervalct ARGS((TimeInterval i1 , TimeInterval i2 ));
  150. int32 intervalov ARGS((TimeInterval i1 , TimeInterval i2 ));
  151. AbsoluteTime intervalstart ARGS((TimeInterval i ));
  152. AbsoluteTime intervalend ARGS((TimeInterval i ));
  153.  
  154.         /* ========== USER I/O ROUTINES ========== */
  155.  
  156. /*
  157.  *    abstimein    - converts a time string to an internal format
  158.  *              checks syntax and range of datetime,
  159.  *              returns time as long integer in respect of GMT
  160.  */
  161.  
  162. AbsoluteTime    
  163. abstimein(datetime)
  164.     char    *datetime;
  165. {
  166.     int        which;
  167.     AbsoluteTime    time_;
  168.     struct tm    brokentime;
  169.  
  170.     if ( TimeDiffIsInited == false ) {
  171. #ifdef linux
  172.         time_t ti;
  173.         CurrentLocalTime = (struct tm *) malloc (sizeof(struct tm));
  174.             time(&ti);
  175.             memcpy(CurrentLocalTime, localtime(&ti), sizeof(struct tm));
  176.         timezonename = tzname[CurrentLocalTime -> tm_isdst];
  177. #else
  178.         TimeDifferenceFromGMT = (struct timeb *)
  179.           malloc( sizeof(struct timeb));
  180.         ftime(TimeDifferenceFromGMT);
  181.         timezonename = (char *) timezone ( TimeDifferenceFromGMT->timezone,
  182.                     TimeDifferenceFromGMT->dstflag ) ;
  183. #endif
  184.         TimeDiffIsInited = true;
  185.     }
  186.  
  187.     which = isabstime(datetime, &brokentime);
  188.  
  189.     switch (which) {
  190.  
  191.     case 3:                            /* epoch */
  192.         time_ = MIN_ABSTIME;
  193.         break;
  194.  
  195.     case 2:                            /* now */
  196.         time_ = GetCurrentTransactionStartTime();
  197.         break;
  198.  
  199.     case 1:                            /* from user */
  200.         (void) timeinsec(&brokentime, &time_);
  201.  
  202.         /* user inputs in local time, we need to store things
  203.          * in GMT so that moving databases across timezones
  204.          * (amongst other things) behave predictably
  205.          */
  206.  
  207.         time_ = time_ +
  208. #ifdef linux
  209.           timezone - (CurrentLocalTime -> tm_isdst) * 3600;
  210. #else
  211.           (TimeDifferenceFromGMT->timezone * 60 ) -
  212.             ( TimeDifferenceFromGMT->dstflag * 3600 ) ;
  213. #endif
  214.           
  215.         
  216.         break;
  217.  
  218.     case 0:                            /* error */
  219.         time_ = INVALID_ABSTIME;
  220.         break;
  221.     }
  222.  
  223.     return(time_);
  224. }
  225.  
  226. /*
  227.  *    abstimeout    - converts the internal time format to a string
  228.  */
  229. char    *
  230. abstimeout(datetime)
  231.     AbsoluteTime    datetime;
  232.     /* seconds in respect of Greenwich Mean Time GMT!! */
  233. {
  234.     extern    struct tm    *gmtime();
  235.     extern    char        *asctime();
  236.     extern    char        *index();
  237.     extern    char        *strcpy();
  238.     struct tm        *brokentime;
  239.     /*points to static structure in gmtime*/
  240.     char            *datestring, *p;
  241.     int            i;
  242.  
  243.     if ( TimeDiffIsInited == false ) {
  244. #ifdef linux
  245.         time_t ti;
  246.         CurrentLocalTime = (struct tm *) malloc (sizeof(struct tm));
  247.             time(&ti);
  248.             memcpy(CurrentLocalTime, localtime(&ti), sizeof(struct tm));
  249.         timezonename = tzname[CurrentLocalTime -> tm_isdst];
  250. #else
  251.         TimeDifferenceFromGMT = (struct timeb *)
  252.           malloc( sizeof(struct timeb));
  253.         ftime(TimeDifferenceFromGMT);
  254.         timezonename = (char *) timezone ( TimeDifferenceFromGMT->timezone,
  255.                     TimeDifferenceFromGMT->dstflag ) ;
  256. #endif
  257.         TimeDiffIsInited = true;
  258.     }
  259.  
  260.     if (datetime == INVALID_ABSTIME) {
  261.         datestring = (char *) palloc ( INVALID_ABSTIME_STR_LEN +1 );
  262.         (void) strcpy(datestring,INVALID_ABSTIME_STR);
  263.     } else if ( datetime == 0 ) {
  264.         datestring = (char *)palloc ( TIME_EPOCH_STR_LEN + 1 );
  265.         (void) strcpy(datestring, TIME_EPOCH_STR );
  266.     } else   {
  267.         /* Using localtime instead of gmtime
  268.          * does the correct conversion !!!
  269.          */
  270.         char *temp_date_string = NULL;
  271.  
  272.         brokentime = localtime((long *) &datetime);
  273.         temp_date_string = asctime(brokentime);
  274.  
  275.         /* add ten to the length because we want to append
  276.          * the local timezone spec which might be up to GMT+xx:xx
  277.          */
  278.  
  279.         datestring = (char *)palloc ( strlen ( temp_date_string ) + 10 );
  280.  
  281.         (void) strcpy(datestring, 
  282.               temp_date_string + 4 );    /* skip name of day */
  283.  
  284.         /* change new-line character "\n" at the end to timezone 
  285.            followed by a null */
  286.         p = index(datestring,'\n');
  287.         *p = ' ';
  288.  
  289.         strcpy ( p+1 , timezonename );
  290.     }
  291.     return(datestring);
  292. }
  293.  
  294.  
  295. /*
  296.  *    reltimein    - converts a reltime string in an internal format
  297.  */
  298. int32    /* RelativeTime */
  299. reltimein(timestring)
  300.     char    *timestring;
  301. {
  302.     int        error;
  303.     int32 /* RelativeTime */    timeinsec;
  304.     int        sign, unitnr;
  305.     long        quantity;
  306.  
  307.     error = isreltime(timestring, &sign, &quantity, &unitnr);
  308.  
  309. #ifdef    DATEDEBUG
  310.     elog(DEBUG, "reltimein: isreltime(%s) returns error=%d, %d, %d, %d",
  311.         timestring, error, sign, quantity, unitnr);
  312. #endif    /* !DATEDEBUG */
  313.  
  314.     if (error != 1) {
  315.         timeinsec = INVALID_RELTIME;  /*invalid time representation */
  316.     } else {
  317.         /* this check is necessary, while no control on overflow */
  318.         if (quantity > unit_max_quantity[unitnr] || quantity < 0) {
  319. #ifdef    DATEDEBUG
  320.             elog(DEBUG, "reltimein: illegal quantity %d (< %d)",
  321.                 quantity, unit_max_quantity[unitnr]);
  322. #endif    /* DATEDEBUG */
  323.             timeinsec = INVALID_RELTIME; /* illegal quantity */
  324.         } else {
  325.             timeinsec = sign * quantity * sec_tab[unitnr];
  326. #ifdef    DATEDEBUG
  327.             elog(DEBUG, "reltimein: computed timeinsec %d",
  328.                 timeinsec);
  329. #endif    /* DATEDEBUG */
  330.             if (timeinsec > MAX_RELTIME || 
  331.                     timeinsec < - MAX_RELTIME) {
  332.                 timeinsec = INVALID_RELTIME;
  333.             }
  334.         }
  335.     }
  336. /*
  337.     if (timeinsec == INVALID_RELTIME)
  338.         (void) printf("\n\tInvalid RelTime");
  339. */
  340.     if (timeinsec == InvalidTime) {
  341.         elog(WARN, "reltimein: cannot handle reltime of 0 secs, yet");
  342.         return(0);
  343.     } else if (timeinsec == INVALID_ABSTIME) {
  344.         timeinsec = InvalidTime;
  345.     }
  346.     return(timeinsec);
  347. }
  348.  
  349.  
  350. /*
  351.  *    reltimeout    - converts the internal format to a reltime string
  352.  */
  353. char    *
  354. reltimeout(timevalue)
  355.     int32 /* RelativeTime */    timevalue;
  356. {    extern char    *sprintf();
  357.     char        *timestring;
  358.     long        quantity;
  359.     register int    i;
  360.     int        unitnr;
  361.  
  362.     timestring = (char *) palloc(Max(strlen(INVALID_RELTIME_STR),
  363.                      UNITMAXLEN));
  364.     (void) strcpy(timestring,INVALID_RELTIME_STR);
  365.     if (timevalue == INVALID_RELTIME)
  366.         return(timestring);
  367.     if (timevalue == 0)
  368.         i = 1; /* unit = 'seconds' */
  369.     else
  370.         for (i = 12; i >= 0; i = i-2)
  371.             if ((timevalue % sec_tab[i]) == 0)
  372.                 break;  /* appropriate unit found */
  373.     unitnr = i;
  374.     quantity = (timevalue / sec_tab[unitnr]);
  375.     if (quantity > 1 || quantity < -1)
  376.         unitnr++;  /* adjust index for PLURAL of unit */
  377.     timestring = (char *) palloc(Max(strlen(INVALID_RELTIME_STR),
  378.                      UNITMAXLEN));
  379.     if (quantity >= 0)
  380.         (void) sprintf( timestring, "%c %u %s", RELTIME_LABEL,
  381.                    quantity, unit_tab[unitnr]);
  382.     else
  383.         (void) sprintf( timestring, "%c %u %s %s", RELTIME_LABEL,
  384.                    (quantity * -1), unit_tab[unitnr], RELTIME_PAST);
  385.     return(timestring);
  386. }
  387.  
  388.  
  389. /*
  390.  *    tintervalin    - converts an interval string to an internal format
  391.  */
  392. TimeInterval    
  393. tintervalin(intervalstr)
  394.     char    *intervalstr;
  395. {    
  396.     int         error;
  397.     AbsoluteTime    i_start, i_end;
  398.     TimeInterval    interval;
  399.  
  400.     interval = (TimeInterval) palloc(sizeof(TimeIntervalData));
  401.     error = istinterval(intervalstr, &i_start, &i_end);
  402.     if (error == 0)    /* not a valid interval NOT IMPLEMENTED */
  403.         interval->status = T_INTERVAL_INVAL;
  404.     else {
  405.         interval->data[0] = Min(i_start, i_end);
  406.         interval->data[1] = Max(i_start, i_end);
  407.         interval->status = T_INTERVAL_VALID;
  408.         /* suppose valid range*/
  409.         if (interval->data[0] == INVALID_ABSTIME ||
  410.             interval->data[1] == INVALID_ABSTIME)
  411.             interval->status = T_INTERVAL_UNCOM;  /* uncomplete */
  412.         if (interval->data[0] == INVALID_ABSTIME &&
  413.             interval->data[1] == INVALID_ABSTIME)
  414.             interval->status = T_INTERVAL_INVAL;  /* undefined  */
  415.     }
  416.     return(interval);
  417. }
  418.  
  419.  
  420. /*
  421.  *    tintervalout    - converts an internal interval format to a string
  422.  *
  423.  */
  424. char    *
  425. tintervalout(interval)
  426.     TimeInterval    interval;
  427. {    extern    char    *abstimeout();
  428.     extern    char    *strcat();
  429.     extern    char    *strcpy();
  430.     char    *i_str, *p;
  431.  
  432.     i_str = (char    *) palloc( T_INTERVAL_LEN );  /* ['...' '...'] */
  433.     p = (char *) palloc(T_INTERVAL_LEN);
  434.     (void) strcpy(i_str,"[\'");
  435.     if (interval->status == T_INTERVAL_INVAL)
  436.         (void) strcat(i_str,INVALID_INTERVAL_STR);
  437.     else {
  438.         p = nabstimeout(interval->data[0]);
  439.         (void) strcat(i_str,p);
  440.         (void) strcat(i_str,"\' \'");
  441.         p = nabstimeout(interval->data[1]);
  442.         (void) strcat(i_str,nabstimeout(interval->data[1]));
  443.     }
  444.     (void) strcat(i_str,"\']\0");
  445.     return(i_str);
  446. }
  447.  
  448.  
  449.          /* ========== PUBLIC ROUTINES ========== */
  450.  
  451.  
  452. /*
  453.  *    timemi        - returns the value of (AbsTime_t1 - RelTime_t2)
  454.  */
  455. AbsoluteTime
  456. timemi(AbsTime_t1, RelTime_t2)
  457.     AbsoluteTime    AbsTime_t1;
  458.     RelativeTime    RelTime_t2;
  459. {
  460.        AbsoluteTime    t;
  461.  
  462.        if (InAbsTimeInterval(AbsTime_t1) && InRelTimeInterval(RelTime_t2)) {
  463.            t = AbsTime_t1 - RelTime_t2;
  464.            if (InAbsTimeInterval(t))
  465.                return(t);
  466.        }
  467.        return(INVALID_ABSTIME);
  468. }
  469.  
  470.  
  471. /*
  472.  *    timepl        - returns the avlue of (AbsTime_t1 + RelTime_t2)
  473.  */
  474. AbsoluteTime
  475. timepl(AbsTime_t1,RelTime_t2)
  476.     AbsoluteTime    AbsTime_t1;
  477.     RelativeTime    RelTime_t2;
  478. {
  479.     AbsoluteTime    t;
  480.  
  481.     if (InAbsTimeInterval(AbsTime_t1) && InRelTimeInterval(RelTime_t2)) {
  482.         t = AbsTime_t1 + RelTime_t2;
  483.         if (InAbsTimeInterval(t))
  484.             return(t);
  485.     }
  486.     return(INVALID_ABSTIME);
  487. }
  488.  
  489.  
  490. /*
  491.  *    ininterval    - returns 1, iff absolute date is in the interval
  492.  */
  493. int
  494. ininterval(t, interval)
  495.     int32    /* AbsoluteTime */    t;
  496.     TimeInterval    interval;
  497. {
  498.     if (interval->status == T_INTERVAL_VALID) {
  499.         if (t >= (int32)interval->data[0] &&
  500.                 t <= (int32)interval->data[1]) {
  501.  
  502.             return(1);    /* t in valid interval */
  503.         }
  504.     }
  505.     return(0);
  506. }
  507.  
  508. /*
  509.  *    intervalrel    - returns  relative time corresponding to interval
  510.  */
  511. RelativeTime
  512. intervalrel(interval)
  513.     TimeInterval    interval;
  514. {
  515.     if (interval->status == T_INTERVAL_VALID)
  516.         return(timemi(interval->data[1], interval->data[0]));
  517.     else
  518.         return(INVALID_RELTIME);
  519. }
  520.  
  521.  
  522. /*
  523.  *    timenow        - returns  time "now", internal format
  524.  *
  525.  *      Now AbsoluteTime is time since Jan 1 1970 -mer 7 Feb 1992
  526.  */
  527. AbsoluteTime    
  528. timenow()
  529. {
  530.     struct timeval tp;
  531.     struct timezone tzp;
  532.  
  533.     (void) gettimeofday(&tp, &tzp);
  534.     return((AbsoluteTime)tp.tv_sec);
  535. }
  536.  
  537.  
  538. /*
  539.  *    timenowout    - returns a pointer to "<current_date_and_time>"
  540.  */
  541. char    *
  542. timenowout()
  543. {
  544.     extern            gettimeofday();
  545.     extern    struct tm     *localtime();
  546.     extern    char        *asctime();
  547.  
  548.     struct timeval    *tp;
  549.     struct timezone *tzp;
  550.     struct tm    *brokentime;
  551.     long        sec;
  552.     int        i;
  553.     char        *datestring;
  554.  
  555.     tp = (struct timeval *) palloc(sizeof(struct timeval));
  556.     tzp= (struct timezone *) palloc(sizeof(struct timezone));
  557.     (void) gettimeofday(tp, tzp);
  558.     sec = tp->tv_sec;
  559.     brokentime = (struct tm *) palloc(sizeof(struct tm));
  560.     brokentime = localtime(&sec);
  561.     datestring = asctime(brokentime);
  562.     for (i=0; i<=3; i++)
  563.         datestring=datestring++;
  564.     return(datestring);
  565. }
  566.  
  567.  
  568. /*
  569.  *    reltimeeq    - returns 1, iff arguments are equal
  570.  *    reltimene    - returns 1, iff arguments are not equal
  571.  *    reltimelt    - returns 1, iff t1 less than t2
  572.  *    reltimegt    - returns 1, iff t1 greater than t2
  573.  *    reltimele    - returns 1, iff t1 less than or equal to t2
  574.  *    reltimege    - returns 1, iff t1 greater than or equal to t2
  575.  */
  576. int32
  577. reltimeeq(t1,t2)
  578.     RelativeTime    t1,t2;
  579. { return(t1 == t2); }
  580.  
  581. int32
  582. reltimene(t1, t2)
  583.     RelativeTime    t1,t2;
  584. { return(t1 != t2); }
  585.  
  586. int32
  587. reltimelt(t1, t2)
  588.     int32 /* RelativeTime */    t1,t2;
  589. { return(t1 < t2); }
  590.  
  591. int32
  592. reltimegt(t1, t2)
  593.     int32 /* RelativeTime */    t1,t2;
  594. { return(t1 > t2); }
  595.  
  596. int32
  597. reltimele(t1, t2)
  598.     int32 /* RelativeTime */    t1,t2;
  599. { return(t1 <= t2); }
  600.  
  601. int32
  602. reltimege(t1, t2)
  603.     int32 /* RelativeTime */    t1,t2;
  604. { return(t1 >= t2); }
  605.  
  606.  
  607. /*
  608.  *    intervaleq    - returns 1, iff interval i1 is equal to interval i2
  609.  */
  610. int32
  611. intervaleq(i1, i2)
  612.     TimeInterval    i1, i2;
  613. {
  614.     Assert(0);    /* XXX */
  615.  
  616.     if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
  617.         return(0);    /* invalid interval */
  618.     return((i1->data[0] == i2->data[0]) &&
  619.            (i1->data[1] == i2->data[1]) );
  620. }
  621.  
  622. /*
  623.  *    intervalleneq    - returns 1, iff length of interval i is equal to
  624.  *                reltime t
  625.  */
  626. int32
  627. intervalleneq(i,t)
  628.     TimeInterval    i;
  629.     RelativeTime    t;
  630. {
  631.     Assert(0);    /* XXX */
  632.  
  633.     if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME))
  634.         return(0);
  635.     return ( (intervalrel(i) == t));
  636. }
  637.  
  638. /*
  639.  *    intervallenne    - returns 1, iff length of interval i is not equal
  640.  *                to reltime t
  641.  */
  642. int32
  643. intervallenne(i,t)
  644.     TimeInterval    i;
  645.     RelativeTime    t;
  646. {
  647.     Assert(0);    /* XXX */
  648.  
  649.     if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME))
  650.         return(0);
  651.     return ( (intervalrel(i) != t));
  652. }
  653.  
  654. /*
  655.  *    intervallenlt    - returns 1, iff length of interval i is less than
  656.  *                reltime t
  657.  */
  658. int32
  659. intervallenlt(i,t)
  660.     TimeInterval    i;
  661.     RelativeTime    t;
  662. {
  663.     Assert(0);    /* XXX */
  664.  
  665.     if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME))
  666.         return(0);
  667.     return ( (intervalrel(i) < t));
  668. }
  669.  
  670. /*
  671.  *    intervallengt    - returns 1, iff length of interval i is greater than
  672.  *                reltime t
  673.  */
  674. int32
  675. intervallengt(i,t)
  676.     TimeInterval    i;
  677.     RelativeTime    t;
  678. {
  679.     Assert(0);    /* XXX */
  680.  
  681.     if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME))
  682.         return(0);
  683.     return ( (intervalrel(i) > t));
  684. }
  685.  
  686. /*
  687.  *    intervallenle    - returns 1, iff length of interval i is less or equal
  688.  *                    than reltime t
  689.  */
  690. int32
  691. intervallenle(i,t)
  692.     TimeInterval    i;
  693.     RelativeTime    t;
  694. {    
  695.     Assert(0);    /* XXX */
  696.  
  697.     if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME))
  698.         return(0);
  699.     return ( (intervalrel(i) <= t));
  700. }
  701.  
  702. /*
  703.  *    intervallenge    - returns 1, iff length of interval i is greater or
  704.  *                 equal than reltime t
  705.  */
  706. int32
  707. intervallenge(i,t)
  708.     TimeInterval    i;
  709.     RelativeTime    t;
  710. {
  711.     Assert(0);    /* XXX */
  712.  
  713.     if ((i->status == T_INTERVAL_INVAL) || (t == INVALID_RELTIME))
  714.         return(0);
  715.     return ( (intervalrel(i) >= t));
  716. }
  717.  
  718. /*
  719.  *    intervalct    - returns 1, iff interval i1 contains interval i2
  720.  */
  721. int32
  722. intervalct(i1,i2)
  723.     TimeInterval    i1, i2;
  724. {
  725.     Assert(0);    /* XXX */
  726.  
  727.     if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
  728.         return(0);    /* invalid interval */
  729.     return((i1->data[0] <= i2->data[0]) &&
  730.            (i1->data[1] >= i2->data[1]) );
  731. }
  732.  
  733. /*
  734.  *    intervalov    - returns 1, iff interval i1 (partially) overlaps i2
  735.  */
  736. int32
  737. intervalov(i1, i2)
  738.     TimeInterval    i1, i2;
  739. {
  740.     Assert(0);    /* XXX */
  741.  
  742.     if (i1->status == T_INTERVAL_INVAL || i2->status == T_INTERVAL_INVAL)
  743.         return(0);    /* invalid interval */
  744.     return(ininterval(i2->data[0], i1) ||
  745.            ininterval(i2->data[1], i1) );
  746. }
  747.  
  748. /*
  749.  *    intervalstart    - returns  the start of interval i
  750.  */
  751. AbsoluteTime
  752. intervalstart(i)
  753.     TimeInterval    i;
  754. {
  755.     return(i->data[0]);
  756. }
  757.  
  758. /*
  759.  *    intervalend    - returns  the end of interval i
  760.  */
  761. AbsoluteTime
  762. intervalend(i)
  763.     TimeInterval    i;
  764. {
  765.     return(i->data[1]);
  766. }
  767.  
  768.  
  769.          /* ========== PRIVATE ROUTINES ========== */
  770.  
  771.  
  772. /*
  773.  * These are support routines for the old abstime implementation.  As
  774.  * far as I know they are no longer used...
  775.  *
  776.  *    correct_month    - returns 1, iff month is a correct month descriptor
  777.  *                     else 0.
  778.  *    output parameter:
  779.  *        num:    points to an integer which is an index 
  780.  *            in table month_name[]
  781.  */
  782. int
  783. correct_month(month, num)
  784.     char    month[];
  785.     int    *num;            /* number of month 0,...,11 */
  786. {
  787.     extern    int    strncmp();
  788.     extern    char    *month_name[];
  789.     int        i = 0;
  790.  
  791.     while (i <= 11) {
  792.         if (strncmp(month, month_name[i],3) == 0) {
  793.             *num = i;
  794.             return(1);
  795.         }
  796.         i++;
  797.     }
  798.     return(0);  /* invalid month describtion */
  799. }
  800.  
  801. /*
  802.  *    isleap        - returns 1, iff year is a leap year
  803.  */
  804. int
  805. isleap(year)
  806.     int    year;
  807. {
  808.     return(year%4 == 0 && year%100 != 0 || year%400 == 0);
  809. }
  810.  
  811.  
  812. /*
  813.  *    timeinsec    - returns 1, iff a valid date is given, otherwise 0
  814.  *
  815.  *    output parameter
  816.  *        seconds:    date in seconds (in respect of GMT!)
  817.  */
  818. int
  819. timeinsec(t, seconds)
  820.     struct tm    *t;
  821.     AbsoluteTime    *seconds;    /* absolute time in seconds */
  822. {
  823.     register long    sec;
  824.     register int    year, mon;
  825.  
  826.     if (t == NULL)    
  827.         return(0);
  828.     sec = 0;
  829.     *seconds = INVALID_ABSTIME;
  830.     year = t->tm_year + TM_YEAR_BASE;
  831.     mon = t->tm_mon + 1;  /* mon  1,...,12 */
  832.     if (year >= EPOCH_YEAR) {
  833.         /* collect days, maybe also the Feb 29. */
  834.         if (isleap(year) && mon > 2)
  835.             ++sec;
  836.         for (--year; year >= EPOCH_YEAR; --year)
  837.             sec += isleap(year) ? DAYS_PER_LYEAR : DAYS_PER_NYEAR;
  838.         --mon;  /* mon  0,...,11 */
  839.         while(--mon >= 0)
  840.             sec += day_tab[0][mon];
  841.         sec += t->tm_mday - 1;
  842.         sec = HOURS_PER_DAY * sec + t->tm_hour;
  843.         sec = MINS_PER_HOUR * sec + t->tm_min;
  844.         sec = SECS_PER_MIN * sec + t->tm_sec;
  845.         /* year >= EPOCH_YEAR ==> sec >= 0 , otherwise overflow!! */
  846.         if (sec >= 0 && sec <= MAX_ABSTIME) {
  847.             *seconds = sec;    /* seconds in respect of */
  848.             return(1);      /*  Greenwich Mean Time GMT */
  849.         } else
  850.             return(0);
  851.     } else {    /* collect days, maby also the Feb 29. */
  852.         if(isleap(year) && mon <= 2)
  853.             ++sec;
  854.         for (++year; year < EPOCH_YEAR; ++year)
  855.             sec += isleap(year) ? DAYS_PER_LYEAR : DAYS_PER_NYEAR;
  856.         --mon;  /* mon  0,...,11 */
  857.         while(++mon <= 11)
  858.             sec += day_tab[0][mon];
  859.         sec += day_tab[isleap(t->tm_year)][t->tm_mon] - t->tm_mday;
  860.         sec = HOURS_PER_DAY * sec + (24 - (t->tm_hour + 1));
  861.         sec = MINS_PER_HOUR * sec + (60 - (t->tm_min + 1));
  862.         sec = SECS_PER_MIN * sec + (60 - t->tm_sec);
  863.         sec = -sec; /* year was less then EPOCH_YEAR !! */
  864.         /* year < EPOCH_YEAR ==> sec < 0 , otherwise overflow!! */
  865.         if (sec < 0 && sec >= MIN_ABSTIME) {
  866.             *seconds = sec;    /* seconds in respect of */
  867.             return(1);      /*  Greenwich Mean Time GMT */
  868.         } else
  869.             return(0);
  870.     }
  871. }
  872.  
  873.  
  874. /*
  875.  *    isreltime    - returns 1, iff datestring is of type reltime
  876.  *                  2, iff datestring is 'invalid time' identifier
  877.  *                  0, iff datestring contains a syntax error
  878.  *
  879.  *    output parameter:
  880.  *        sign = -1, iff direction is 'ago'
  881.  *                   else sign = 1.
  882.  *        quantity   : quantity of unit
  883.  *        unitnr     :    0 or 1 ... sec
  884.  *                2 or 3 ... min
  885.  *                4 or 5 ... hour
  886.  *                6 or 7 ... day
  887.  *                8 or 9 ... week
  888.  *                   10 or 11... month
  889.  *                   12 or 13... year
  890.  *              
  891.  *
  892.  *    Relative time:
  893.  *
  894.  *    `@' ` ' Quantity ` ' Unit [ ` ' Direction]
  895.  *
  896.  *    OR  `Undefined RelTime'     (see also INVALID_RELTIME_STR)
  897.  *
  898.  *    where
  899.  *    Quantity is    `1', `2', ...
  900.  *    Unit is        `second', `minute', `hour', `day', `week',
  901.  *            `month' (30-days), or `year' (365-days),
  902.  *                 or PLURAL of these units.
  903.  *    Direction is    `ago'
  904.  *
  905.  *    VALID time  less or equal   `@ 68 years' 
  906.  *
  907.  */
  908. int
  909. isreltime(timestring, sign, quantity, unitnr)
  910.     char    *timestring;
  911.     int    *sign, *unitnr;
  912.     long    *quantity;
  913. {
  914.     extern    int    strncmp();
  915.     extern     char    *strcpy();
  916.     register char    *p;
  917.     register char    c;
  918.     int        i;
  919.     char        unit[UNITMAXLEN] ;
  920.     char        direction[DIRMAXLEN];
  921.     int        localSign;
  922.     int        localUnitNumber;
  923.     long        localQuantity;
  924.  
  925.     if (!PointerIsValid(sign)) {
  926.         sign = &localSign;
  927.     }
  928.     if (!PointerIsValid(unitnr)) {
  929.         unitnr = &localUnitNumber;
  930.     }
  931.     if (!PointerIsValid(quantity)) {
  932.         quantity = &localQuantity;
  933.     }
  934.     unit[0] = '\0';
  935.     direction[0] = '\0';
  936.     p = timestring;
  937.     /* skip leading blanks */
  938.     while (c = *p) {
  939.         if (c != ' ')
  940.             break;
  941.         p++;
  942.     }
  943.     /* Test whether 'invalid time' identifier or not */
  944.     if (!strncmp(INVALID_RELTIME_STR,p,strlen(INVALID_RELTIME_STR) + 1))
  945.         return(2);    /* correct 'invalid time' identifier found */
  946.  
  947.     /* handle label of relative time */
  948.     if (c != RELTIME_LABEL)
  949.         return(0);    /*syntax error*/
  950.     c = *++p;
  951.     if (c != ' ')    return(0);    /*syntax error*/
  952.     p++;
  953.     /* handle the quantity */
  954.     *quantity = 0;
  955.     for (;;) {
  956.         c = *p;
  957.         if (isdigit(c)) {
  958.             *quantity = *quantity * 10 + (c -'0');
  959.             p++;
  960.         } else {
  961.             if (c == ' ' )
  962.                 break;         /* correct quantity found */
  963.             else
  964.                 return(0);     /* syntax error */
  965.         }
  966.     }
  967.     /* handle unit */
  968.     p++;
  969.     i = 0;
  970.     for (;;) {
  971.         c = *p;
  972.         if (c >= 'a' && c <= 'z' && i <= (UNITMAXLEN - 1)) {
  973.             unit[i] = c;
  974.             p++;
  975.             i++;
  976.         } else {
  977.             if ((c == ' ' || c == '\0')
  978.                 && correct_unit(unit, unitnr))
  979.                 break;        /* correct unit found */
  980.             else
  981.                 return(0);    /* syntax error */
  982.         }
  983.     }
  984.     /* handle optional direction */
  985.     if (c == ' ')
  986.         p++;
  987.     i = 0;
  988.     *sign = 1;
  989.     for (;;) {
  990.         c = *p;
  991.         if (c >= 'a' && c <= 'z' && i <= (DIRMAXLEN - 1)) {
  992.             direction[i] = c;
  993.             p++;
  994.             i++;
  995.         } else {
  996.             if ((c == ' ' || c == NULL) && i == 0) {
  997.                 *sign = 1;
  998.                 break;  /* no direction specified */
  999.             }
  1000.             if ((c == ' ' || c == '\0') && i != 0)
  1001.             {
  1002.                 direction[i] = '\0';
  1003.                 correct_dir(direction, sign);
  1004.                 break;      /* correct direction found */
  1005.             }
  1006.             else
  1007.                 return(0);     /* syntax error*/
  1008.         }
  1009.     }
  1010.     return(1);
  1011. }
  1012.  
  1013. /*
  1014.  *    correct_unit    - returns 1, iff unit is a correct unit description
  1015.  *
  1016.  *    output parameter:
  1017.  *        unptr: points to an integer which is the appropriate unit number
  1018.  *               (see function isreltime())
  1019.  */
  1020. int
  1021. correct_unit(unit, unptr)
  1022.     char    unit[];
  1023.     int    *unptr;
  1024. {
  1025.     int    j = 0;
  1026.  
  1027.     while (j >= 0) {
  1028.         if (strncmp(unit, unit_tab[j], strlen(unit_tab[j])) == 0) {
  1029.             *unptr = j;
  1030.             return(1);
  1031.         }
  1032.         j++;
  1033.     }
  1034.     return (0); /* invalid unit descriptor */
  1035. }
  1036.  
  1037. /*
  1038.  *    correct_dir    - returns 1, iff direction is a correct identifier
  1039.  *
  1040.  *    output parameter:
  1041.  *        signptr: points to -1 if dir corresponds to past tense
  1042.  *             else  to 1
  1043.  */
  1044. int
  1045. correct_dir(direction,signptr)
  1046.     char    direction[];
  1047.     int    *signptr;
  1048. {    
  1049.     *signptr = 1;
  1050.     if (strncmp(RELTIME_PAST, direction, strlen(RELTIME_PAST)+1) == 0)
  1051.     {
  1052.         *signptr = -1;
  1053.         return(1);
  1054.     } else
  1055.         return (0);  /* invalid direction descriptor */
  1056. }
  1057.  
  1058.  
  1059. /*
  1060.  *    istinterval    - returns 1, iff i_string is a valid interval descr.
  1061.  *                  0, iff i_string is NOT a valid interval desc.
  1062.  *                  2, iff any time is INVALID_ABSTIME
  1063.  *
  1064.  *    output parameter:
  1065.  *        i_start, i_end: interval margins
  1066.  *
  1067.  *    Time interval:
  1068.  *    `[' {` '} `'' <AbsTime> `'' {` '} `'' <AbsTime> `'' {` '} `]'
  1069.  *
  1070.  *    OR  `Undefined Range'    (see also INVALID_INTERVAL_STR)
  1071.  *
  1072.  *    where <AbsTime> satisfies the syntax of absolute time.
  1073.  *
  1074.  *    e.g.  [  '  Jan 18 1902'   'Jan 1 00:00:00 1970']
  1075.  */
  1076. int
  1077. istinterval(i_string, i_start, i_end)
  1078.     char    *i_string;
  1079.     AbsoluteTime    *i_start, *i_end;
  1080. {
  1081.     extern    AbsoluteTime    abstimein();
  1082.     register char        *p,*p1;
  1083.     register char        c;
  1084.  
  1085.     p = i_string;
  1086.     /* skip leading blanks up to '[' */
  1087.     while (c = *p) {
  1088.         if ( IsSpace(c))
  1089.             p++;
  1090.         else if (c != '[')
  1091.             return(0); /* syntax error */
  1092.         else
  1093.             break;
  1094.     }
  1095.     p++;
  1096.     /* skip leading blanks up to "'" */
  1097.     while (c = *p) {
  1098.         if (IsSpace(c))
  1099.             p++;
  1100.         else if (c != '\'')
  1101.             return (0);    /* syntax error */
  1102.         else
  1103.             break;
  1104.     }
  1105.     p++;
  1106.     if (strncmp(INVALID_INTERVAL_STR,p,strlen(INVALID_INTERVAL_STR)) == 0)
  1107.         return(0);    /* undefined range, handled like a syntax err.*/
  1108.     /* search for the end of the first date and change it to a NULL*/
  1109.     p1 = p;
  1110.     while (c = *p1) {
  1111.         if ( c == '\'') {
  1112.             *p1 = NULL;
  1113.             break;
  1114.             }
  1115.         p1++;
  1116.     }
  1117.     /* get the first date */
  1118.     *i_start = nabstimein(p);    /* first absolute date */
  1119.     /* rechange NULL at the end of the first date to a "'" */
  1120.     *p1 = '\'';
  1121.     p = ++p1;
  1122.     /* skip blanks up to "'", beginning of second date*/
  1123.     while (c = *p) {
  1124.         if (IsSpace(c))
  1125.             p++;
  1126.         else if (c != '\'')
  1127.             return (0);    /* syntax error */
  1128.         else
  1129.             break;
  1130.     }    
  1131.     p++;
  1132.     /* search for the end of the second date and change it to a NULL*/
  1133.     p1 = p;
  1134.     while (c = *p1) {
  1135.         if ( c == '\'') {
  1136.             *p1 = NULL;
  1137.             break;
  1138.         }
  1139.         p1++;
  1140.     }
  1141.     /* get the second date */
  1142.     *i_end = nabstimein(p);        /* second absolute date */
  1143.     /* rechange NULL at the end of the first date to a ''' */
  1144.     *p1 = '\'';
  1145.     p = ++p1;
  1146.     /* skip blanks up to ']'*/
  1147.     while (c = *p) {
  1148.         if ( IsSpace(c))
  1149.             p++;
  1150.         else if (c != ']')
  1151.             return(0); /*syntax error */
  1152.         else
  1153.             break;
  1154.     }
  1155.     p++;
  1156.     c = *p;
  1157.     if ( ! IsNull(c))
  1158.         return (0);    /* syntax error */
  1159.     /* it seems to be a valid interval */
  1160.     return(1);    
  1161. }
  1162.